package com.itany.corejava.code12_线程;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 石小俊
 * @date 2023年05月16日 11:33
 */
public class Test10_线程单例 {

    public static void main(String[] args) {
        MyThreadLocal<String> local = new MyThreadLocal<>();
        // 当前main方法属于主线程
        // 此时存储的数据的key即为当前线程
        // 以下三个数据是同一个key
        // 后面的会覆盖前面的

        // 通过原始的get/setXxx方法实现的
        Map<Thread, String> map = new HashMap<>();
        // 向集合中存储数据
        map.put(Thread.currentThread(), "admin");
        // 将集合交给MyThreadLocal对象
        local.setLocal(map);
        System.out.println(Thread.currentThread() + "线程:" + local.getLocal().get(Thread.currentThread()));
        map.put(Thread.currentThread(), "alice");
        local.setLocal(map);
        System.out.println(Thread.currentThread() + "线程:" + local.getLocal().get(Thread.currentThread()));
        map.put(Thread.currentThread(), "jack");
        local.setLocal(map);
        System.out.println(Thread.currentThread() + "线程:" + local.getLocal().get(Thread.currentThread()));

        new Thread() {
            @Override
            public void run() {
                Map<Thread, String> map = new HashMap<>();
                map.put(Thread.currentThread(), "admin");
                local.setLocal(map);
                System.out.println(Thread.currentThread() + "线程:" + local.getLocal().get(Thread.currentThread()));
            }
        }.start();
        System.out.println(Thread.currentThread() + "线程:" + local.getLocal().get(Thread.currentThread()));
    }

}

class MyThreadLocal<T> {
    // 实现线程单例,表示同一个线程获取的是同一个对象
    // 在属性中设置一个Map集合,其key对应线程,同一个线程只能存放一个对象
    // 再次为该线程存放对象,会覆盖原有的对象
    private Map<Thread, T> local = new HashMap<>();

    public Map<Thread, T> getLocal() {
        return local;
    }

    public void setLocal(Map<Thread, T> local) {
        this.local = local;
    }

    // 模拟ThreadLocal的方法
    /**
     * 在对应的线程中获取对应的值
     * @return
     */
    public Object get() {
        return local.get(Thread.currentThread());
    }

    /**
     * 向当前线程中存储一个数据
     * @param t
     */
    public void set(T t) {
        local.put(Thread.currentThread(), t);
    }
}
